#include "LRUcache.h"

LRUnode::LRUnode(std::vector<std::string> node)
:_node(node){}


LRUnode::LRUnode(const LRUnode& rhs){
    if(_node.size()!=0){
        _node.clear();
    }
    _node=rhs._node;
}


LRUnode::~LRUnode(){}


std::vector<std::string>& LRUnode::getNode(){
    return _node;
}

LRUcache::LRUcache(std::size_t size)
:_size(size){}


LRUcache::LRUcache(const LRUcache& rhs)
:_size(rhs._size)
,_que(rhs._que)
,_queIndex(rhs._queIndex){}


LRUcache& LRUcache::operator=(const LRUcache & rhs){
    _size = rhs._size;
    _que = rhs._que;
    _queIndex = rhs._queIndex;
    return *this;
}


LRUcache::~LRUcache(){}




void LRUcache::LRUpush(std::string& key,std::vector<std::string>& node)
{
    auto it=_queIndex.find(key);
    if(it!=_queIndex.end())
    {
        int idx=_queIndex[key];
        if(idx!=0)
        {
            std::swap(_que[idx],_que[idx-1]);
            for(auto &x:_queIndex)
            {
                if(x.second==(idx-1))
                {
                    std::swap(_queIndex[key],x.second);
                    break;
                }
            }
        }
        return;
    }
    if(_que.size()==_size)
    {
        _que.pop_back();
        _que.push_back(std::move(LRUnode(node)));
        
        for(auto &x:_queIndex)
        {
            if(x.second==(_size-1))
            {
                _queIndex.erase(x.first);
            }
        }
        _queIndex.insert(std::make_pair(key,_size-1));
        return;
    }
    _que.push_back(std::move(LRUnode(node)));
    _queIndex[key]=_que.size()-1;
}

std::vector<std::string>& LRUcache::LRUsearch(std::string& key)
{
    auto it=_queIndex.find(key);
    if(it!=_queIndex.end())
    {
        int idx=_queIndex[key];
        if(idx!=0)
        {
            std::swap(_que[idx],_que[idx-1]);
            for(auto &x:_queIndex)
            {
                if(x.second==(idx-1))
                {
                    std::swap(_queIndex[key],x.second);
                    break;
                }
            }
        }
        return _que[_queIndex[key]].getNode(); 
    }
    return *(new std::vector<std::string>);
}

void LRUcache::writeQue(std::string& filename)
{
    std::ofstream ofs(filename,std::ios_base::trunc);
    std::map<int,std::string,std::less<int>> temp;
    for(auto &x:_queIndex)
    {
        std::cout<<x.first<<" "<<x.second<<std::endl;
        temp.insert(std::make_pair(x.second,x.first));
    }
    for(auto &x:temp)
    {
        ofs<<x.second;
        std::vector<std::string> vec=LRUsearch(x.second);
        for(auto &y:vec)
        {
            ofs<<" "<<y;
        }
        ofs<<std::endl;
    }
    ofs.close();
}


